package com.example.terminalservice.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.terminalservice.common.MenuTypeEnum;
import com.example.terminalservice.common.Result;
import com.example.terminalservice.mapper.RoleMenuMapper;
import com.example.terminalservice.pojo.Menu;
import com.example.terminalservice.service.MenuService;
import com.example.terminalservice.mapper.MenuMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author 28142
* @description 针对表【sys_menu】的数据库操作Service实现
* @createDate 2023-08-05 13:34:14
*/
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu>
    implements MenuService{
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public Result findAll() {
        List<Menu> list = list(new LambdaQueryWrapper<Menu>().orderByAsc(Menu::getPriority));
        // 获取一级菜单
        List<Menu> pMenus = list.stream().filter(menu -> menu.getPid() == null).collect(Collectors.toList());
        List<Menu> menus = getChildMenu(list, pMenus);
        return Result.success(menus);
    }

    /**
     * 递归函数，传入一个菜单集合和一个父菜单，循环获取并设置其子菜单
     * @author 杨雨盛
     * @date 2023/8/5 19:59
     * @param list
     * @param pMenu
     * @return java.util.List<com.example.terminalservice.pojo.Menu>
     */
    public List<Menu> getChildMenu(List<Menu> list, List<Menu> pMenu) {
        for (Menu menu : pMenu) {
            List<Menu> cMenus = list.stream().filter(m -> menu.getId().equals(m.getPid())).collect(Collectors.toList());
            // 设置子菜单
            menu.setChildren(cMenus);
            // 调用自身
            getChildMenu(list, cMenus);
        }
        return pMenu;
    }

    @Override
    public Result getMenusByRole(Integer roleId) {
        List<Menu> list = menuMapper.getMenusByRole(roleId);
        List<Menu> pMenus = list.stream().filter(menu -> menu.getPid() == null).collect(Collectors.toList());
        return Result.success(getChildMenu(list, pMenus));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean setMenusByRole(Integer roleId, List<Integer> ids) {
        // 补全菜单
        ids = completeMenu(ids);
        // 删除角色对应菜单
        roleMenuMapper.deleteByRoleId(roleId);
        // 批量插入数据
        roleMenuMapper.insertBatch(roleId, ids);
        return true;
    }

    /**
     * 递归补全菜单
     * @author 杨雨盛
     * @date 2023/8/7 0:34
     * @param ids
     * @return java.util.List<java.lang.Integer>
     */
    public List<Integer> completeMenu(List<Integer> ids) {
        // 当前端传递的菜单缺少一级菜单时，补上
        List<Integer> idsCopy = CollUtil.newArrayList(ids);
        for (Integer id : idsCopy) {
            Menu menu = getById(id);
            // 如果是子菜单并且前端没有传递其父菜单，补上
            if (menu.getPid() != null && !ids.contains(menu.getPid())) {
                ids.add(menu.getPid());
                completeMenu(ids);
            }
        }
        return ids;
    }

    @Override
    public Result getParent(Integer type) {
        List<Map<String, Object>> list = null;
        // 如果选择的类型是菜单，要查询所有目录；如果选择的类型是按钮，要查询所有菜单
        if (MenuTypeEnum.MENU.getId().equals(type)) {
            list = getListByType(MenuTypeEnum.DIRECTORY.getId());
        } else if (MenuTypeEnum.BUTTON.getId().equals(type)) {
            list = getListByType(MenuTypeEnum.MENU.getId());
        }
        return Result.success(list);
    }

    /**
     * 根据类型查询菜单列表
     *
     * @param type
     * @return java.util.List<com.example.terminalservice.pojo.Menu>
     * @author 杨雨盛
     * @date 2023/8/7 9:33
     */
    public List<Map<String, Object>> getListByType(Integer type) {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Menu::getId, Menu::getTitle).eq(Menu::getType, type);
        return listMaps(wrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean delMenu(Integer id, Integer type) {
        // 如果是按钮，直接删除；如果是目录或者菜单，级联删除
        if (MenuTypeEnum.BUTTON.getId().equals(type)) {
            removeById(id);
        } else if (MenuTypeEnum.MENU.getId().equals(type)){
            LambdaUpdateWrapper<Menu> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(Menu::getPid, id);
            // 删除菜单本身
            removeById(id);
            // 删除其下所有按钮
            remove(wrapper);
        } else if (MenuTypeEnum.DIRECTORY.getId().equals(type)) {
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Menu::getPid, id);
            // 获取其下所有二级菜单的id
            List<Integer> ids = list(wrapper).stream().map(Menu::getId).collect(Collectors.toList());
            // 删除目录本身
            removeById(id);
            // 删除其下所有二级菜单
            removeBatchByIds(ids);
            // 删除其下所有三级按钮，pid为二级菜单id的全部删除
            menuMapper.delBatchByPids(ids);
        }
        return true;
    }

    @Override
    public List<Menu> getMenusByRoles(List<Integer> ids) {
        // 根据角色集合查找出所有一级目录和二级菜单集合
        List<Menu> list = menuMapper.getMenusByRoles(ids);
        List<Menu> pMenus = list.stream().filter(m -> m.getPid() == null).collect(Collectors.toList());
        System.out.println(pMenus);
        for (Menu menu : pMenus) {
            List<Menu> cMenus = list.stream().filter(m -> menu.getId().equals(m.getPid())).collect(Collectors.toList());
            menu.setChildren(cMenus);
        }
        System.out.println(pMenus);
        return pMenus;
    }

}




